package com.cn.wanxi.service.impl;

import com.cn.wanxi.common.ParseTool;
import com.cn.wanxi.common.RedisNumTool;
import com.cn.wanxi.common.ThreadTool;
import com.cn.wanxi.entity.NewsEntity;
import com.cn.wanxi.entity.ResultEntity;
import com.cn.wanxi.mapper.NewsMapper;
import com.cn.wanxi.service.INewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;

@Service
public class NewsServiceImpl implements INewsService {
    @Autowired
    private NewsMapper newsMapper;

    @Override
    public ResultEntity add(NewsEntity newsEntity) {
        int result = newsMapper.add(newsEntity);
        resetCache(result, 0);
        return ResultEntity.success(result);
    }

    @Override
    public ResultEntity update(NewsEntity newsEntity) {
        int result = newsMapper.update(newsEntity);
        resetCache(result, newsEntity.getId());
        return ResultEntity.success(result);
    }

    @Override
    public ResultEntity delete(NewsEntity newsEntity) {
        int result = newsMapper.delete(newsEntity);
        resetCache(result, newsEntity.getId());
        return ResultEntity.success(result);
    }

    @Override
    public List<NewsEntity> findAll(NewsEntity newsEntity) {
        final List<NewsEntity>[] list = new List[]{new ArrayList<>()};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                list[0] = findAllCache(newsEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return list[0];
    }

    @Override
    public ResultEntity<NewsEntity> findById(NewsEntity newsEntity) {
        final NewsEntity[] model = {new NewsEntity()};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                model[0] = findByIdCache(newsEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return ResultEntity.success(model[0]);
    }

    @Override
    public Integer getCount(NewsEntity newsEntity) {
        final int[] result = {-1};
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                result[0] = findCount(newsEntity);
            }
        });
        thread.start();
        ThreadTool.ThreadSleep(thread);
        return result[0];
    }

    @Override
    public ResultEntity findPrevious(NewsEntity newsModel) {
        NewsEntity model = newsMapper.findPrevious(newsModel);
        if (model == null) {
            return ResultEntity.failed();
        }
        return ResultEntity.success(model);
    }

    @Override
    public ResultEntity findNext(NewsEntity newsModel) {
        NewsEntity model = newsMapper.findNext(newsModel);
        if (model == null) {
            return  ResultEntity.failed();
        }
        return ResultEntity.success(model);
    }

    /**
     * 查找所有新闻缓存
     *
     * @return
     */
    private synchronized List<NewsEntity> findAllCache(NewsEntity newsModel) {
        List<NewsEntity> list = new ArrayList<>();
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_NEWS);
        boolean cache = jedis.exists("newsModelId") && judgeModel(newsModel);
        if (cache) {
            Long length = jedis.llen("newsModelId");
            for (int i = 0; i < length; i++) {
                NewsEntity model = new NewsEntity();
                model.setId(ParseTool.StringToInt(jedis.lindex("newsModelId", i)));
                model.setTypeId(ParseTool.StringToInt(jedis.lindex("newsModelTypeId", i)));
                model.setTitle(jedis.lindex("newsModelTitle", i));
                model.setAuthor(jedis.lindex("newsModelAuthor", i));
                model.setOutline(jedis.lindex("newsModelOutline", i));
                model.setContent(jedis.lindex("newsModelContent", i));
                model.setTop(ParseTool.StringToInt(jedis.lindex("newsModelTop", i)));
                model.setHot(ParseTool.StringToInt(jedis.lindex("newsModelHot", i)));
                model.setEnable(ParseTool.StringToInt(jedis.lindex("newsModelEnable", i)));
                model.setCreateTime(jedis.lindex("newsModelCreateTime", i));
                model.setUpdateTime(jedis.lindex("newsModelUpdateTime", i));
                list.add(model);
            }
        } else {
            list = newsMapper.findAll(newsModel);
            if (judgeModel(newsModel)) {
                for (NewsEntity model :
                        list) {
                    jedis.rpush("newsModelId", String.valueOf(model.getId()));
                    jedis.rpush("newsModelTypeId", String.valueOf(model.getTypeId()));
                    jedis.rpush("newsModelTitle", model.getTitle());
                    jedis.rpush("newsModelAuthor", model.getAuthor());
                    jedis.rpush("newsModelOutline", model.getOutline());
                    jedis.rpush("newsModelContent", model.getContent());
                    jedis.rpush("newsModelTop", String.valueOf(model.getTop()));
                    jedis.rpush("newsModelHot", String.valueOf(model.getHot()));
                    jedis.rpush("newsModelEnable", String.valueOf(model.getEnable()));
                    jedis.rpush("newsModelCreateTime", model.getCreateTime());
                    jedis.rpush("newsModelUpdateTime", model.getUpdateTime());
                }
            }
        }
        return list;
    }

    /**
     * 根据新闻Id查找单个新闻缓存
     *
     * @param newsModel
     * @return
     */
    private synchronized NewsEntity findByIdCache(NewsEntity newsModel) {
        NewsEntity model = new NewsEntity();
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_NEWS);
        String cacheName = "newsModel_id_" + newsModel.getId();
        boolean cache = jedis.exists(cacheName);
        if (cache) {
            model.setId(ParseTool.StringToInt(jedis.hget(cacheName, "id")));
            model.setTypeId(ParseTool.StringToInt(jedis.hget(cacheName, "typeId")));
            model.setTitle(jedis.hget(cacheName, "title"));
            model.setAuthor(jedis.hget(cacheName, "author"));
            model.setTop(ParseTool.StringToInt(jedis.hget(cacheName, "top")));
            model.setHot(ParseTool.StringToInt(jedis.hget(cacheName, "hot")));
            model.setOutline(jedis.hget(cacheName, "outline"));
            model.setContent(jedis.hget(cacheName, "content"));
            model.setEnable(ParseTool.StringToInt(jedis.hget(cacheName, "enable")));
            model.setCreateTime(jedis.hget(cacheName, "createTime"));
            model.setUpdateTime(jedis.hget(cacheName, "updateTime"));
            model.setVisits(ParseTool.StringToInt(jedis.hget(cacheName, "visits")));
            jedis.hincrBy(cacheName, "visits", 1);
            /*设为热点*/
            if (Integer.parseInt(jedis.hget(cacheName, "visits")) == 100) {
                model.setHot(1);
                model.setStart("");
                model.setEnd("");
                newsMapper.update(model);
            }
        } else {
            model = newsMapper.findById(newsModel);
            jedis.hset(cacheName, "id", String.valueOf(model.getId()));
            jedis.hset(cacheName, "typeId", String.valueOf(model.getTypeId()));
            jedis.hset(cacheName, "title", model.getTitle());
            jedis.hset(cacheName, "author", model.getAuthor());
            jedis.hset(cacheName, "top", String.valueOf(model.getTop()));
            jedis.hset(cacheName, "hot", String.valueOf(model.getHot()));
            jedis.hset(cacheName, "outline", model.getOutline());
            jedis.hset(cacheName, "content", model.getContent());
            jedis.hset(cacheName, "enable", String.valueOf(model.getEnable()));
            jedis.hset(cacheName, "createTime", model.getCreateTime());
            jedis.hset(cacheName, "updateTime", model.getUpdateTime());
            jedis.hset(cacheName, "visits", "1");
            /*取消热点*/
            if (Integer.parseInt(jedis.hget(cacheName, "visits")) == 1) {
                model.setHot(0);
                model.setStart("");
                model.setEnd("");
                newsMapper.update(model);
            }
        }
        return model;
    }

    /**
     * 查找总数缓存
     *
     * @param newsModel
     * @return
     */
    private synchronized int findCount(NewsEntity newsModel) {
        int result = -1;
        Jedis jedis = new Jedis();
        jedis.select(RedisNumTool.REDIS_NEWS);
        boolean cache = jedis.exists("newsModelCount") && judgeModel(newsModel);
        if (cache) {
            result = ParseTool.StringToInt(jedis.get("newsModelCount"));
        } else {
            result = newsMapper.getCount(newsModel);
            if (judgeModel(newsModel)) {
                jedis.set("newsModelCount", String.valueOf(result));
            }
        }
        return result;
    }

    /**
     * 清除Redis内缓存
     *
     * @param result
     * @param id
     */
    private void resetCache(int result, int id) {
        if (result > 0) {
            Jedis jedis = new Jedis();
            jedis.select(RedisNumTool.REDIS_NEWS);
            jedis.del("newsModelId", "newsModelTypeId",
                    "newsModelTitle", "newsModelAuthor",
                    "newsModelOutline", "newsModelContent",
                    "newsModelTop", "newsModelHot",
                    "newsModelEnable", "newsModelCreateTime", "newsModelUpdateTime");
            jedis.del("newsModelCount");
            jedis.del("newsModel_id_" + id);
        }
    }

    /**
     * 判断model内是否有值
     * 没有值返回true
     *
     * @param model
     * @return
     */
    private boolean judgeModel(NewsEntity model) {
        return model.getId() == null &&
                model.getTypeId() == null &&
                model.getTitle() == null &&
                model.getUpdateTime() == null &&
                model.getAuthor() == null &&
                model.getOutline() == null &&
                model.getContent() == null &&
                model.getStart() == null &&
                model.getEnd() == null &&
                ParseTool.enableToInt(model.getEnable()) == 1 &&
                ParseTool.pageToInt(model.getPage()) == 1 &&
                ParseTool.limitToInt(model.getLimit()) == 10;
    }
}
